/*
* Copyright (C) 1997-2001 Id Software, Inc.
* 
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
* 
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE.
* 
* See the GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*  
*/

// Created on 28.12.2003 by RST.
// $Id: GameTarget.java,v 1.8 2006/01/21 21:53:31 salomo Exp $
using System;
using Defines = Suake2.UI.Defines;
using Globals = Suake2.UI.Globals;
using Lib = Suake2.UI.util.Lib;
using Math3D = Suake2.UI.util.Math3D;
namespace Suake2.UI.game
{
	
	public class GameTarget
	{
		public class AnonymousClassEntUseAdapter:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "Use_Target_Tent";
				}
				
			}
			public override void  use(edict_t ent, edict_t other, edict_t activator)
			{
				GameBase.gi.WriteByte(Defines.svc_temp_entity);
				GameBase.gi.WriteByte(ent.style);
				GameBase.gi.WritePosition(ent.s.origin);
				GameBase.gi.multicast(ent.s.origin, Defines.MULTICAST_PVS);
			}
		}
		public class AnonymousClassEntUseAdapter1:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "Use_Target_Speaker";
				}
				
			}
			public override void  use(edict_t ent, edict_t other, edict_t activator)
			{
				int chan;
				
				if ((ent.spawnflags & 3) != 0)
				{
					// looping sound toggles
					if (ent.s.sound != 0)
						ent.s.sound = 0;
					// turn it off
					else
						ent.s.sound = ent.noise_index; // start it
				}
				else
				{
					// normal sound
					if ((ent.spawnflags & 4) != 0)
						chan = Defines.CHAN_VOICE | Defines.CHAN_RELIABLE;
					else
						chan = Defines.CHAN_VOICE;
					// use a positioned_sound, because this entity won't normally be
					// sent to any clients because it is invisible
					GameBase.gi.positioned_sound(ent.s.origin, ent, chan, ent.noise_index, ent.volume, ent.attenuation, 0);
				}
			}
		}
		public class AnonymousClassEntUseAdapter2:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "Use_Target_Help";
				}
				
			}
			public override void  use(edict_t ent, edict_t other, edict_t activator)
			{
				
				if ((ent.spawnflags & 1) != 0)
					GameBase.game.helpmessage1 = ent.message;
				else
					GameBase.game.helpmessage2 = ent.message;
				
				GameBase.game.helpchanged++;
			}
		}
		public class AnonymousClassEntUseAdapter3:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "use_target_secret";
				}
				
			}
			public override void  use(edict_t ent, edict_t other, edict_t activator)
			{
				GameBase.gi.sound(ent, Defines.CHAN_VOICE, ent.noise_index, 1, Defines.ATTN_NORM, 0);
				
				GameBase.level.found_secrets++;
				
				GameUtil.G_UseTargets(ent, activator);
				GameUtil.G_FreeEdict(ent);
			}
		}
		public class AnonymousClassEntUseAdapter4:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "use_target_goal";
				}
				
			}
			public override void  use(edict_t ent, edict_t other, edict_t activator)
			{
				GameBase.gi.sound(ent, Defines.CHAN_VOICE, ent.noise_index, 1, Defines.ATTN_NORM, 0);
				
				GameBase.level.found_goals++;
				
				if (GameBase.level.found_goals == GameBase.level.total_goals)
					GameBase.gi.configstring(Defines.CS_CDTRACK, "0");
				
				GameUtil.G_UseTargets(ent, activator);
				GameUtil.G_FreeEdict(ent);
			}
		}
		public class AnonymousClassEntThinkAdapter:EntThinkAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_explosion_explode";
				}
				
			}
			public override bool think(edict_t self)
			{
				
				float save;
				
				GameBase.gi.WriteByte(Defines.svc_temp_entity);
				GameBase.gi.WriteByte(Defines.TE_EXPLOSION1);
				GameBase.gi.WritePosition(self.s.origin);
				GameBase.gi.multicast(self.s.origin, Defines.MULTICAST_PHS);
				
				GameCombat.T_RadiusDamage(self, self.activator, self.dmg, null, self.dmg + 40, Defines.MOD_EXPLOSIVE);
				
				save = self.delay;
				self.delay = 0;
				GameUtil.G_UseTargets(self, self.activator);
				self.delay = save;
				return true;
			}
		}
		public class AnonymousClassEntUseAdapter5:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "use_target_explosion";
				}
				
			}
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				self.activator = activator;
				
				if (0 == self.delay)
				{
					jake2.game.GameTarget.target_explosion_explode.think(self);
					return ;
				}
				
				self.think = Suake2.UI.game.GameTarget.target_explosion_explode;
				self.nextthink = GameBase.level.time + self.delay;
			}
		}
		public class AnonymousClassEntUseAdapter6:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "use_target_changelevel";
				}
				
			}
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				if (GameBase.level.intermissiontime != 0)
					return ; // already activated
				
				if (0 == GameBase.deathmatch.value_Renamed && 0 == GameBase.coop.value_Renamed)
				{
					if (GameBase.g_edicts[1].health <= 0)
						return ;
				}
				
				// if noexit, do a ton of damage to other
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				if (GameBase.deathmatch.value_Renamed != 0 && 0 == ((int) GameBase.dmflags.value_Renamed & Defines.DF_ALLOW_EXIT) && other != GameBase.g_edicts[0])
				{
					GameCombat.T_Damage(other, self, self, Globals.vec3_origin, other.s.origin, Globals.vec3_origin, 10 * other.max_health, 1000, 0, Defines.MOD_EXIT);
					return ;
				}
				
				// if multiplayer, let everyone know who hit the exit
				if (GameBase.deathmatch.value_Renamed != 0)
				{
					if (activator != null && activator.client != null)
						GameBase.gi.bprintf(Defines.PRINT_HIGH, activator.client.pers.netname + " exited the level.\n");
				}
				
				// if going to a new unit, clear cross triggers
				if (self.map.IndexOf('*') > - 1)
					GameBase.game.serverflags &= ~ (Defines.SFL_CROSS_TRIGGER_MASK);
				
				PlayerHud.BeginIntermission(self);
			}
		}
		public class AnonymousClassEntUseAdapter7:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "use_target_splash";
				}
				
			}
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				GameBase.gi.WriteByte(Defines.svc_temp_entity);
				GameBase.gi.WriteByte(Defines.TE_SPLASH);
				GameBase.gi.WriteByte(self.count);
				GameBase.gi.WritePosition(self.s.origin);
				GameBase.gi.WriteDir(self.movedir);
				GameBase.gi.WriteByte(self.sounds);
				GameBase.gi.multicast(self.s.origin, Defines.MULTICAST_PVS);
				
				if (self.dmg != 0)
					GameCombat.T_RadiusDamage(self, activator, self.dmg, null, self.dmg + 40, Defines.MOD_SPLASH);
			}
		}
		public class AnonymousClassEntUseAdapter8:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "use_target_spawner";
				}
				
			}
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				edict_t ent;
				
				ent = GameUtil.G_Spawn();
				ent.classname = self.target;
				Math3D.VectorCopy(self.s.origin, ent.s.origin);
				Math3D.VectorCopy(self.s.angles, ent.s.angles);
				GameSpawn.ED_CallSpawn(ent);
				GameBase.gi.unlinkentity(ent);
				GameUtil.KillBox(ent);
				GameBase.gi.linkentity(ent);
				if (self.speed != 0)
					Math3D.VectorCopy(self.movedir, ent.velocity);
			}
		}
		public class AnonymousClassEntUseAdapter9:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "use_target_blaster";
				}
				
			}
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				int effect;
				
				if ((self.spawnflags & 2) != 0)
					effect = 0;
				else if ((self.spawnflags & 1) != 0)
					effect = Defines.EF_HYPERBLASTER;
				else
					effect = Defines.EF_BLASTER;
				
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				GameWeapon.fire_blaster(self, self.s.origin, self.movedir, self.dmg, (int) self.speed, Defines.EF_BLASTER, Defines.MOD_TARGET_BLASTER != 0);
				GameBase.gi.sound(self, Defines.CHAN_VOICE, self.noise_index, 1, Defines.ATTN_NORM, 0);
			}
		}
		public class AnonymousClassEntUseAdapter10:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "trigger_crosslevel_trigger_use";
				}
				
			}
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				GameBase.game.serverflags |= self.spawnflags;
				GameUtil.G_FreeEdict(self);
			}
		}
		public class AnonymousClassEntThinkAdapter1:EntThinkAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_crosslevel_target_think";
				}
				
			}
			public override bool think(edict_t self)
			{
				if (self.spawnflags == (GameBase.game.serverflags & Defines.SFL_CROSS_TRIGGER_MASK & self.spawnflags))
				{
					GameUtil.G_UseTargets(self, self);
					GameUtil.G_FreeEdict(self);
				}
				return true;
			}
		}
		public class AnonymousClassEntThinkAdapter2:EntThinkAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_laser_think";
				}
				
			}
			public override bool think(edict_t self)
			{
				
				edict_t ignore;
				float[] start = new float[]{0, 0, 0};
				float[] end = new float[]{0, 0, 0};
				trace_t tr;
				float[] point = new float[]{0, 0, 0};
				float[] last_movedir = new float[]{0, 0, 0};
				int count;
				
				if ((self.spawnflags & unchecked((int) 0x80000000)) != 0)
					count = 8;
				else
					count = 4;
				
				if (self.enemy != null)
				{
					Math3D.VectorCopy(self.movedir, last_movedir);
					Math3D.VectorMA(self.enemy.absmin, 0.5f, self.enemy.size, point);
					Math3D.VectorSubtract(point, self.s.origin, self.movedir);
					Math3D.VectorNormalize(self.movedir);
					if (!Math3D.VectorEquals(self.movedir, last_movedir))
						self.spawnflags |= unchecked((int) 0x80000000);
				}
				
				ignore = self;
				Math3D.VectorCopy(self.s.origin, start);
				Math3D.VectorMA(start, 2048, self.movedir, end);
				while (true)
				{
					tr = GameBase.gi.trace(start, null, null, end, ignore, Defines.CONTENTS_SOLID | Defines.CONTENTS_MONSTER | Defines.CONTENTS_DEADMONSTER);
					
					if (tr.ent == null)
						break;
					
					// hurt it if we can
					if ((tr.ent.takedamage != 0) && 0 == (tr.ent.flags & Defines.FL_IMMUNE_LASER))
						GameCombat.T_Damage(tr.ent, self, self.activator, self.movedir, tr.endpos, Globals.vec3_origin, self.dmg, 1, Defines.DAMAGE_ENERGY, Defines.MOD_TARGET_LASER);
					
					// if we hit something that's not a monster or player or is
					// immune to lasers, we're done
					if (0 == (tr.ent.svflags & Defines.SVF_MONSTER) && (null == tr.ent.client))
					{
						if ((self.spawnflags & unchecked((int) 0x80000000)) != 0)
						{
							self.spawnflags &= ~ unchecked((int) 0x80000000);
							GameBase.gi.WriteByte(Defines.svc_temp_entity);
							GameBase.gi.WriteByte(Defines.TE_LASER_SPARKS);
							GameBase.gi.WriteByte(count);
							GameBase.gi.WritePosition(tr.endpos);
							GameBase.gi.WriteDir(tr.plane.normal);
							GameBase.gi.WriteByte(self.s.skinnum);
							GameBase.gi.multicast(tr.endpos, Defines.MULTICAST_PVS);
						}
						break;
					}
					
					ignore = tr.ent;
					Math3D.VectorCopy(tr.endpos, start);
				}
				
				Math3D.VectorCopy(tr.endpos, self.s.old_origin);
				
				self.nextthink = GameBase.level.time + Defines.FRAMETIME;
				return true;
			}
		}
		public class AnonymousClassEntUseAdapter11:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_laser_use";
				}
				
			}
			
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				self.activator = activator;
				if ((self.spawnflags & 1) != 0)
					jake2.game.GameTarget.target_laser_off(self);
				else
					jake2.game.GameTarget.target_laser_on(self);
			}
		}
		public class AnonymousClassEntThinkAdapter3:EntThinkAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_laser_start";
				}
				
			}
			public override bool think(edict_t self)
			{
				
				self.movetype = Defines.MOVETYPE_NONE;
				self.solid = Defines.SOLID_NOT;
				self.s.renderfx |= Defines.RF_BEAM | Defines.RF_TRANSLUCENT;
				self.s.modelindex = 1; // must be non-zero
				
				// set the beam diameter
				if ((self.spawnflags & 64) != 0)
					self.s.frame = 16;
				else
					self.s.frame = 4;
				
				// set the color
				if ((self.spawnflags & 2) != 0)
					self.s.skinnum = unchecked((int) 0xf2f2f0f0);
				else if ((self.spawnflags & 4) != 0)
					self.s.skinnum = unchecked((int) 0xd0d1d2d3);
				else if ((self.spawnflags & 8) != 0)
					self.s.skinnum = unchecked((int) 0xf3f3f1f1);
				else if ((self.spawnflags & 16) != 0)
					self.s.skinnum = unchecked((int) 0xdcdddedf);
				else if ((self.spawnflags & 32) != 0)
					self.s.skinnum = unchecked((int) 0xe0e1e2e3);
				
				if (null == self.enemy)
				{
					if (self.target != null)
					{
						EdictIterator edit = GameBase.G_Find(null, GameBase.findByTarget, self.target);
						if (edit == null)
							GameBase.gi.dprintf(self.classname + " at " + Lib.vtos(self.s.origin) + ": " + self.target + " is a bad target\n");
						self.enemy = edit.o;
					}
					else
					{
						GameBase.G_SetMovedir(self.s.angles, self.movedir);
					}
				}
				self.use = Suake2.UI.game.GameTarget.target_laser_use;
				self.think = Suake2.UI.game.GameTarget.target_laser_think;
				
				if (0 == self.dmg)
					self.dmg = 1;
				
				Math3D.VectorSet(self.mins, - 8, - 8, - 8);
				Math3D.VectorSet(self.maxs, 8, 8, 8);
				GameBase.gi.linkentity(self);
				
				if ((self.spawnflags & 1) != 0)
					jake2.game.GameTarget.target_laser_on(self);
				else
					jake2.game.GameTarget.target_laser_off(self);
				return true;
			}
		}
		public class AnonymousClassEntThinkAdapter4:EntThinkAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_lightramp_think";
				}
				
			}
			public override bool think(edict_t self)
			{
				
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				char[] tmp = new char[]{(char) ('a' + (int) (self.movedir[0] + (GameBase.level.time - self.timestamp) / Defines.FRAMETIME * self.movedir[2]))};
				
				GameBase.gi.configstring(Defines.CS_LIGHTS + self.enemy.style, new System.String(tmp));
				
				if ((GameBase.level.time - self.timestamp) < self.speed)
				{
					self.nextthink = GameBase.level.time + Defines.FRAMETIME;
				}
				else if ((self.spawnflags & 1) != 0)
				{
					char temp;
					
					//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
					temp = (char) self.movedir[0];
					self.movedir[0] = self.movedir[1];
					self.movedir[1] = temp;
					self.movedir[2] *= (- 1);
				}
				
				return true;
			}
		}
		public class AnonymousClassEntUseAdapter12:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_lightramp_use";
				}
				
			}
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				if (self.enemy == null)
				{
					edict_t e;
					
					// check all the targets
					e = null;
					EdictIterator es = null;
					
					while (true)
					{
						es = GameBase.G_Find(es, GameBase.findByTarget, self.target);
						
						if (es == null)
							break;
						
						e = es.o;
						
						if (Lib.strcmp(e.classname, "light") != 0)
						{
							GameBase.gi.dprintf(self.classname + " at " + Lib.vtos(self.s.origin));
							GameBase.gi.dprintf("target " + self.target + " (" + e.classname + " at " + Lib.vtos(e.s.origin) + ") is not a light\n");
						}
						else
						{
							self.enemy = e;
						}
					}
					
					if (null == self.enemy)
					{
						GameBase.gi.dprintf(self.classname + " target " + self.target + " not found at " + Lib.vtos(self.s.origin) + "\n");
						GameUtil.G_FreeEdict(self);
						return ;
					}
				}
				
				self.timestamp = GameBase.level.time;
				jake2.game.GameTarget.target_lightramp_think.think(self);
			}
		}
		public class AnonymousClassEntThinkAdapter5:EntThinkAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_earthquake_think";
				}
				
			}
			public override bool think(edict_t self)
			{
				
				int i;
				edict_t e;
				
				if (self.last_move_time < GameBase.level.time)
				{
					GameBase.gi.positioned_sound(self.s.origin, self, Defines.CHAN_AUTO, self.noise_index, 1.0f, Defines.ATTN_NONE, 0);
					self.last_move_time = GameBase.level.time + 0.5f;
				}
				
				for (i = 1; i < GameBase.num_edicts; i++)
				{
					e = GameBase.g_edicts[i];
					
					if (!e.inuse)
						continue;
					if (null == e.client)
						continue;
					if (null == e.groundentity)
						continue;
					
					e.groundentity = null;
					e.velocity[0] += Lib.crandom() * 150;
					e.velocity[1] += Lib.crandom() * 150;
					e.velocity[2] = self.speed * (100.0f / e.mass);
				}
				
				if (GameBase.level.time < self.timestamp)
					self.nextthink = GameBase.level.time + Defines.FRAMETIME;
				
				return true;
			}
		}
		public class AnonymousClassEntUseAdapter13:EntUseAdapter
		{
			override public System.String ID
			{
				get
				{
					return "target_earthquake_use";
				}
				
			}
			public override void  use(edict_t self, edict_t other, edict_t activator)
			{
				self.timestamp = GameBase.level.time + self.count;
				self.nextthink = GameBase.level.time + Defines.FRAMETIME;
				self.activator = activator;
				self.last_move_time = 0;
			}
		}
		
		public static void  SP_target_temp_entity(edict_t ent)
		{
			ent.use = Use_Target_Tent;
		}
		
		public static void  SP_target_speaker(edict_t ent)
		{
			//char buffer[MAX_QPATH];
			System.String buffer;
			
			if (GameBase.st.noise == null)
			{
				GameBase.gi.dprintf("target_speaker with no noise set at " + Lib.vtos(ent.s.origin) + "\n");
				return ;
			}
			if (GameBase.st.noise.IndexOf(".wav") < 0)
				buffer = "" + GameBase.st.noise + ".wav";
			else
				buffer = GameBase.st.noise;
			
			ent.noise_index = GameBase.gi.soundindex(buffer);
			
			if (ent.volume == 0)
				ent.volume = 1.0f;
			
			if (ent.attenuation == 0)
				ent.attenuation = 1.0f;
			else if (ent.attenuation == - 1)
			// use -1 so 0 defaults to 1
				ent.attenuation = 0;
			
			// check for prestarted looping sound
			if ((ent.spawnflags & 1) != 0)
				ent.s.sound = ent.noise_index;
			
			ent.use = Use_Target_Speaker;
			
			// must link the entity so we get areas and clusters so
			// the server can determine who to send updates to
			GameBase.gi.linkentity(ent);
		}
		
		/// <summary> QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1 When fired, the
		/// "message" key becomes the current personal computer string, and the
		/// message light will be set on all clients status bars.
		/// </summary>
		public static void  SP_target_help(edict_t ent)
		{
			if (GameBase.deathmatch.value_Renamed != 0)
			{
				// auto-remove for deathmatch
				GameUtil.G_FreeEdict(ent);
				return ;
			}
			
			if (ent.message == null)
			{
				GameBase.gi.dprintf(ent.classname + " with no message at " + Lib.vtos(ent.s.origin) + "\n");
				GameUtil.G_FreeEdict(ent);
				return ;
			}
			ent.use = Use_Target_Help;
		}
		
		public static void  SP_target_secret(edict_t ent)
		{
			if (GameBase.deathmatch.value_Renamed != 0)
			{
				// auto-remove for deathmatch
				GameUtil.G_FreeEdict(ent);
				return ;
			}
			
			ent.use = use_target_secret;
			if (GameBase.st.noise == null)
				GameBase.st.noise = "misc/secret.wav";
			ent.noise_index = GameBase.gi.soundindex(GameBase.st.noise);
			ent.svflags = Defines.SVF_NOCLIENT;
			GameBase.level.total_secrets++;
			// map bug hack
			if (0 == Lib.Q_stricmp(GameBase.level.mapname, "mine3") && ent.s.origin[0] == 280 && ent.s.origin[1] == - 2048 && ent.s.origin[2] == - 624)
				ent.message = "You have found a secret area.";
		}
		
		public static void  SP_target_goal(edict_t ent)
		{
			if (GameBase.deathmatch.value_Renamed != 0)
			{
				// auto-remove for deathmatch
				GameUtil.G_FreeEdict(ent);
				return ;
			}
			
			ent.use = use_target_goal;
			if (GameBase.st.noise == null)
				GameBase.st.noise = "misc/secret.wav";
			ent.noise_index = GameBase.gi.soundindex(GameBase.st.noise);
			ent.svflags = Defines.SVF_NOCLIENT;
			GameBase.level.total_goals++;
		}
		
		public static void  SP_target_explosion(edict_t ent)
		{
			ent.use = use_target_explosion;
			ent.svflags = Defines.SVF_NOCLIENT;
		}
		
		public static void  SP_target_changelevel(edict_t ent)
		{
			if (ent.map == null)
			{
				GameBase.gi.dprintf("target_changelevel with no map at " + Lib.vtos(ent.s.origin) + "\n");
				GameUtil.G_FreeEdict(ent);
				return ;
			}
			
			// ugly hack because *SOMEBODY* screwed up their map
			if ((Lib.Q_stricmp(GameBase.level.mapname, "fact1") == 0) && (Lib.Q_stricmp(ent.map, "fact3") == 0))
				ent.map = "fact3$secret1";
			
			ent.use = use_target_changelevel;
			ent.svflags = Defines.SVF_NOCLIENT;
		}
		
		public static void  SP_target_splash(edict_t self)
		{
			self.use = use_target_splash;
			GameBase.G_SetMovedir(self.s.angles, self.movedir);
			
			if (0 == self.count)
				self.count = 32;
			
			self.svflags = Defines.SVF_NOCLIENT;
		}
		
		public static void  SP_target_spawner(edict_t self)
		{
			self.use = use_target_spawner;
			self.svflags = Defines.SVF_NOCLIENT;
			if (self.speed != 0)
			{
				GameBase.G_SetMovedir(self.s.angles, self.movedir);
				Math3D.VectorScale(self.movedir, self.speed, self.movedir);
			}
		}
		
		public static void  SP_target_blaster(edict_t self)
		{
			self.use = use_target_blaster;
			GameBase.G_SetMovedir(self.s.angles, self.movedir);
			self.noise_index = GameBase.gi.soundindex("weapons/laser2.wav");
			
			if (0 == self.dmg)
				self.dmg = 15;
			if (0 == self.speed)
				self.speed = 1000;
			
			self.svflags = Defines.SVF_NOCLIENT;
		}
		
		public static void  SP_target_crosslevel_trigger(edict_t self)
		{
			self.svflags = Defines.SVF_NOCLIENT;
			self.use = trigger_crosslevel_trigger_use;
		}
		
		public static void  SP_target_crosslevel_target(edict_t self)
		{
			if (0 == self.delay)
				self.delay = 1;
			self.svflags = Defines.SVF_NOCLIENT;
			
			self.think = target_crosslevel_target_think;
			self.nextthink = GameBase.level.time + self.delay;
		}
		
		public static void  target_laser_on(edict_t self)
		{
			if (null == self.activator)
				self.activator = self;
			self.spawnflags |= unchecked((int) 0x80000001);
			self.svflags &= ~ Defines.SVF_NOCLIENT;
			target_laser_think.think(self);
		}
		
		public static void  target_laser_off(edict_t self)
		{
			self.spawnflags &= ~ 1;
			self.svflags |= Defines.SVF_NOCLIENT;
			self.nextthink = 0;
		}
		
		public static void  SP_target_laser(edict_t self)
		{
			// let everything else get spawned before we start firing
			self.think = target_laser_start;
			self.nextthink = GameBase.level.time + 1;
		}
		
		public static void  SP_target_lightramp(edict_t self)
		{
			if (self.message == null || self.message.Length != 2 || self.message[0] < 'a' || self.message[0] > 'z' || self.message[1] < 'a' || self.message[1] > 'z' || self.message[0] == self.message[1])
			{
				GameBase.gi.dprintf("target_lightramp has bad ramp (" + self.message + ") at " + Lib.vtos(self.s.origin) + "\n");
				GameUtil.G_FreeEdict(self);
				return ;
			}
			
			if (GameBase.deathmatch.value_Renamed != 0)
			{
				GameUtil.G_FreeEdict(self);
				return ;
			}
			
			if (self.target == null)
			{
				GameBase.gi.dprintf(self.classname + " with no target at " + Lib.vtos(self.s.origin) + "\n");
				GameUtil.G_FreeEdict(self);
				return ;
			}
			
			self.svflags |= Defines.SVF_NOCLIENT;
			self.use = target_lightramp_use;
			self.think = target_lightramp_think;
			
			self.movedir[0] = self.message[0] - 'a';
			self.movedir[1] = self.message[1] - 'a';
			self.movedir[2] = (self.movedir[1] - self.movedir[0]) / (self.speed / Defines.FRAMETIME);
		}
		
		public static void  SP_target_earthquake(edict_t self)
		{
			if (null == self.targetname)
				GameBase.gi.dprintf("untargeted " + self.classname + " at " + Lib.vtos(self.s.origin) + "\n");
			
			if (0 == self.count)
				self.count = 5;
			
			if (0 == self.speed)
				self.speed = 200;
			
			self.svflags |= Defines.SVF_NOCLIENT;
			self.think = target_earthquake_think;
			self.use = target_earthquake_use;
			
			self.noise_index = GameBase.gi.soundindex("world/quake.wav");
		}
		
		/// <summary> QUAKED target_temp_entity (1 0 0) (-8 -8 -8) (8 8 8) Fire an origin based
		/// temp entity event to the clients. "style" type byte
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'Use_Target_Tent' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		public static EntUseAdapter Use_Target_Tent;
		
		/// <summary> QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off
		/// reliable "noise" wav file to play "attenuation" -1 = none, send to whole
		/// level 1 = normal fighting sounds 2 = idle sound level 3 = ambient sound
		/// level "volume" 0.0 to 1.0
		/// 
		/// Normal sounds play each time the target is used. The reliable flag can be
		/// set for crucial voiceovers.
		/// 
		/// Looped sounds are always atten 3 / vol 1, and the use function toggles it
		/// on/off. Multiple identical looping sounds will just increase volume
		/// without any speed cost.
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'Use_Target_Speaker' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		public static EntUseAdapter Use_Target_Speaker;
		
		
		//UPGRADE_NOTE: The initialization of  'Use_Target_Help' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		public static EntUseAdapter Use_Target_Help;
		
		/// <summary> QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8) Counts a secret found.
		/// These are single use targets.
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'use_target_secret' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntUseAdapter use_target_secret;
		
		/// <summary> QUAKED target_goal (1 0 1) (-8 -8 -8) (8 8 8) Counts a goal completed.
		/// These are single use targets.
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'use_target_goal' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntUseAdapter use_target_goal;
		
		
		/// <summary> QUAKED target_explosion (1 0 0) (-8 -8 -8) (8 8 8) Spawns an explosion
		/// temporary entity when used.
		/// 
		/// "delay" wait this long before going off "dmg" how much radius damage
		/// should be done, defaults to 0
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'target_explosion_explode' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntThinkAdapter target_explosion_explode;
		
		//UPGRADE_NOTE: The initialization of  'use_target_explosion' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntUseAdapter use_target_explosion;
		
		/// <summary> QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8) Changes level to
		/// "map" when fired
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'use_target_changelevel' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntUseAdapter use_target_changelevel;
		
		/// <summary> QUAKED target_splash (1 0 0) (-8 -8 -8) (8 8 8) Creates a particle splash
		/// effect when used.
		/// 
		/// Set "sounds" to one of the following: 1) sparks 2) blue water 3) brown
		/// water 4) slime 5) lava 6) blood
		/// 
		/// "count" how many pixels in the splash "dmg" if set, does a radius damage
		/// at this location when it splashes useful for lava/sparks
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'use_target_splash' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntUseAdapter use_target_splash;
		
		/// <summary> QUAKED target_spawner (1 0 0) (-8 -8 -8) (8 8 8) Set target to the type
		/// of entity you want spawned. Useful for spawning monsters and gibs in the
		/// factory levels.
		/// 
		/// For monsters: Set direction to the facing you want it to have.
		/// 
		/// For gibs: Set direction if you want it moving and speed how fast it
		/// should be moving otherwise it will just be dropped
		/// </summary>
		
		//UPGRADE_NOTE: The initialization of  'use_target_spawner' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntUseAdapter use_target_spawner;
		
		/// <summary> QUAKED target_blaster (1 0 0) (-8 -8 -8) (8 8 8) NOTRAIL NOEFFECTS Fires
		/// a blaster bolt in the set direction when triggered.
		/// 
		/// dmg default is 15 speed default is 1000
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'use_target_blaster' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		public static EntUseAdapter use_target_blaster;
		
		/// <summary> QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1
		/// trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 Once this
		/// trigger is touched/used, any trigger_crosslevel_target with the same
		/// trigger number is automatically used when a level is started within the
		/// same unit. It is OK to check multiple triggers. Message, delay, target,
		/// and killtarget also work.
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'trigger_crosslevel_trigger_use' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		public static EntUseAdapter trigger_crosslevel_trigger_use;
		
		/// <summary> QUAKED target_crosslevel_target (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1
		/// trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 Triggered
		/// by a trigger_crosslevel elsewhere within a unit. If multiple triggers are
		/// checked, all must be true. Delay, target and killtarget also work.
		/// 
		/// "delay" delay before using targets if the trigger has been activated
		/// (default 1)
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'target_crosslevel_target_think' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntThinkAdapter target_crosslevel_target_think;
		
		/// <summary> QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE
		/// YELLOW ORANGE FAT When triggered, fires a laser. You can either set a
		/// target or a direction.
		/// </summary>
		//UPGRADE_NOTE: The initialization of  'target_laser_think' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		public static EntThinkAdapter target_laser_think;
		
		//UPGRADE_NOTE: The initialization of  'target_laser_use' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		public static EntUseAdapter target_laser_use;
		
		//UPGRADE_NOTE: The initialization of  'target_laser_start' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntThinkAdapter target_laser_start;
		
		/// <summary> QUAKED target_lightramp (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE speed How
		/// many seconds the ramping will take message two letters; starting
		/// lightlevel and ending lightlevel
		/// </summary>
		
		//UPGRADE_NOTE: The initialization of  'target_lightramp_think' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntThinkAdapter target_lightramp_think;
		
		//UPGRADE_NOTE: The initialization of  'target_lightramp_use' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntUseAdapter target_lightramp_use;
		
		/// <summary> QUAKED target_earthquake (1 0 0) (-8 -8 -8) (8 8 8) When triggered, this
		/// initiates a level-wide earthquake. All players and monsters are affected.
		/// "speed" severity of the quake (default:200) "count" duration of the quake
		/// (default:5)
		/// </summary>
		
		//UPGRADE_NOTE: The initialization of  'target_earthquake_think' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntThinkAdapter target_earthquake_think;
		
		//UPGRADE_NOTE: The initialization of  'target_earthquake_use' was moved to static method 'jake2.game.GameTarget'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static EntUseAdapter target_earthquake_use;
		static GameTarget()
		{
			Use_Target_Tent = new AnonymousClassEntUseAdapter();
			Use_Target_Speaker = new AnonymousClassEntUseAdapter1();
			Use_Target_Help = new AnonymousClassEntUseAdapter2();
			use_target_secret = new AnonymousClassEntUseAdapter3();
			use_target_goal = new AnonymousClassEntUseAdapter4();
			target_explosion_explode = new AnonymousClassEntThinkAdapter();
			use_target_explosion = new AnonymousClassEntUseAdapter5();
			use_target_changelevel = new AnonymousClassEntUseAdapter6();
			use_target_splash = new AnonymousClassEntUseAdapter7();
			use_target_spawner = new AnonymousClassEntUseAdapter8();
			use_target_blaster = new AnonymousClassEntUseAdapter9();
			trigger_crosslevel_trigger_use = new AnonymousClassEntUseAdapter10();
			target_crosslevel_target_think = new AnonymousClassEntThinkAdapter1();
			target_laser_think = new AnonymousClassEntThinkAdapter2();
			target_laser_use = new AnonymousClassEntUseAdapter11();
			target_laser_start = new AnonymousClassEntThinkAdapter3();
			target_lightramp_think = new AnonymousClassEntThinkAdapter4();
			target_lightramp_use = new AnonymousClassEntUseAdapter12();
			target_earthquake_think = new AnonymousClassEntThinkAdapter5();
			target_earthquake_use = new AnonymousClassEntUseAdapter13();
		}
	}
}